use crate::REQWEST_CLIENT;
use anyhow::Result;
use log::info;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;

/// Mapping to [RPT_BOND_CB_LIST.json](file:///Users/CC/gitee/conanchen/fuquants-workspace/crates/fudacli/eastmoney/sample/RPT_BOND_CB_LIST.json)
#[derive(Debug, Serialize, Deserialize)]
pub struct RptBondCbList {
    pub version: Option<Value>,
    pub result: Option<RptBondCbListResult>,
    pub success: Option<Value>,
    pub message: Option<Value>,
    pub code: Option<Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RptBondCbListResult {
    pub pages: Option<Value>,
    pub data: Vec<RptBondCbListResultData>,
    pub count: Option<Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RptBondCbListResultData {
    #[serde(rename = "SECURITY_CODE")]
    pub security_code: Option<Value>, // 证券代码
    #[serde(rename = "SECUCODE")]
    pub secu_code: Option<Value>, // 证券编码

    #[serde(rename = "TRADE_MARKET")]
    pub trade_market: Option<Value>, // 交易市场

    #[serde(rename = "SECURITY_NAME_ABBR")]
    pub security_name_abbr: Option<Value>, // 证券简称

    #[serde(rename = "DELIST_DATE")]
    pub delist_date: Option<Value>, // 退市日期

    #[serde(rename = "LISTING_DATE")]
    pub listing_date: Option<Value>, // 上市日期

    #[serde(rename = "CONVERT_STOCK_CODE")]
    pub convert_stock_code: Option<Value>, // 转股股票代码

    #[serde(rename = "BOND_EXPIRE")]
    pub bond_expire: Option<Value>, // 债券期限

    #[serde(rename = "RATING")]
    pub rating: Option<Value>, // 信用评级

    #[serde(rename = "VALUE_DATE")]
    pub value_date: Option<Value>, // 发行起始日

    #[serde(rename = "ISSUE_YEAR")]
    pub issue_year: Option<Value>, // 发行年度

    #[serde(rename = "CEASE_DATE")]
    pub cease_date: Option<Value>, // 停止交易日

    #[serde(rename = "EXPIRE_DATE")]
    pub expire_date: Option<Value>, // 到期日

    #[serde(rename = "PAY_INTEREST_DAY")]
    pub pay_interest_day: Option<Value>, // 付息日

    #[serde(rename = "INTEREST_RATE_EXPLAIN")]
    pub interest_rate_explain: Option<Value>, // 利率说明

    #[serde(rename = "BOND_COMBINE_CODE")]
    pub bond_combine_code: Option<Value>, // 债券组合代码

    #[serde(rename = "ACTUAL_ISSUE_SCALE")]
    pub actual_issue_scale: Option<Value>, // 实际发行规模

    #[serde(rename = "ISSUE_PRICE")]
    pub issue_price: Option<Value>, // 发行价格

    #[serde(rename = "REMARK")]
    pub remark: Option<Value>, // 备注

    #[serde(rename = "PAR_VALUE")]
    pub par_value: Option<Value>, // 面值

    #[serde(rename = "ISSUE_OBJECT")]
    pub issue_object: Option<Value>, // 发行对象

    #[serde(rename = "REDEEM_TYPE")]
    pub redeem_type: Option<Value>, // 赎回类型

    #[serde(rename = "EXECUTE_REASON_HS")]
    pub execute_reason_hs: Option<Value>, // 回售触发原因（沪市）

    #[serde(rename = "NOTICE_DATE_HS")]
    pub notice_date_hs: Option<Value>, // 回售公告日（沪市）

    #[serde(rename = "NOTICE_DATE_SH")]
    pub notice_date_sh: Option<Value>, // 回售公告日（深市）

    #[serde(rename = "EXECUTE_PRICE_HS")]
    pub execute_price_hs: Option<Value>, // 回售价格（沪市）

    #[serde(rename = "EXECUTE_PRICE_SH")]
    pub execute_price_sh: Option<Value>, // 回售价格（深市）

    #[serde(rename = "RECORD_DATE_SH")]
    pub record_date_sh: Option<Value>, // 回售登记日（深市）

    #[serde(rename = "EXECUTE_START_DATESH")]
    pub execute_start_date_sh: Option<Value>, // 回售开始日（深市）

    #[serde(rename = "EXECUTE_START_DATEHS")]
    pub execute_start_date_hs: Option<Value>, // 回售开始日（沪市）

    #[serde(rename = "EXECUTE_END_DATE")]
    pub execute_end_date: Option<Value>, // 回售结束日

    #[serde(rename = "CORRECODE")]
    pub correcode: Option<Value>, // 正回购代码

    #[serde(rename = "CORRECODE_NAME_ABBR")]
    pub correcode_name_abbr: Option<Value>, // 正回购简称

    #[serde(rename = "PUBLIC_START_DATE")]
    pub public_start_date: Option<Value>, // 公开发行起始日

    #[serde(rename = "CORRECODEO")]
    pub correcodeo: Option<Value>, // 配债代码

    #[serde(rename = "CORRECODE_NAME_ABBRO")]
    pub correcode_name_abbro: Option<Value>, // 配债简称

    #[serde(rename = "BOND_START_DATE")]
    pub bond_start_date: Option<Value>, // 债券上市日

    #[serde(rename = "SECURITY_START_DATE")]
    pub security_start_date: Option<Value>, // 股权登记日

    #[serde(rename = "SECURITY_SHORT_NAME")]
    pub security_short_name: Option<Value>, // 标的股票简称

    #[serde(rename = "FIRST_PER_PREPLACING")]
    pub first_per_preplacing: Option<Value>, // 首次公开发行优先配售比例

    #[serde(rename = "ONLINE_GENERAL_AAU")]
    pub online_general_aau: Option<u64>, // 网上向社会公众投资者发行数量

    #[serde(rename = "ONLINE_GENERAL_LWR")]
    pub online_general_lwr: Option<Value>, // 网上向社会公众投资者发行中签率

    #[serde(rename = "INITIAL_TRANSFER_PRICE")]
    pub initial_transfer_price: Option<Value>, // 初始转股价格

    #[serde(rename = "TRANSFER_END_DATE")]
    pub transfer_end_date: Option<Value>, // 转股结束日

    #[serde(rename = "TRANSFER_START_DATE")]
    pub transfer_start_date: Option<Value>, // 转股开始日

    #[serde(rename = "RESALE_CLAUSE")]
    pub resale_clause: Option<Value>, // 回售条款

    #[serde(rename = "REDEEM_CLAUSE")]
    pub redeem_clause: Option<Value>, // 赎回条款

    #[serde(rename = "PARTY_NAME")]
    pub party_name: Option<Value>, // 评级机构名称

    #[serde(rename = "CONVERT_STOCK_PRICE")]
    pub convert_stock_price: Option<Value>, // 当前转股价格

    #[serde(rename = "TRANSFER_PRICE")]
    pub transfer_price: Option<Value>, // 转让价格

    #[serde(rename = "TRANSFER_VALUE")]
    pub transfer_value: Option<Value>, // 转让价值

    #[serde(rename = "CURRENT_BOND_PRICE")]
    pub current_bond_price: Option<Value>, // 当前债券价格

    #[serde(rename = "TRANSFER_PREMIUM_RATIO")]
    pub transfer_premium_ratio: Option<Value>, // 转让溢折价率

    #[serde(rename = "CONVERT_STOCK_PRICEHQ")]
    pub convert_stock_pricehq: Option<Value>, // 转股价格沪市

    #[serde(rename = "MARKET")]
    pub market: Option<Value>, // 市场

    #[serde(rename = "RESALE_TRIG_PRICE")]
    pub resale_trig_price: Option<Value>, // 回售触发价格

    #[serde(rename = "REDEEM_TRIG_PRICE")]
    pub redeem_trig_price: Option<Value>, // 赎回触发价格

    #[serde(rename = "PBV_RATIO")]
    pub pbv_ratio: Option<Value>, // 市净率

    #[serde(rename = "IB_START_DATE")]
    pub ib_start_date: Option<Value>, // 投资者回售开始日

    #[serde(rename = "IB_END_DATE")]
    pub ib_end_date: Option<Value>, // 投资者回售结束日

    #[serde(rename = "CASHFLOW_DATE")]
    pub cashflow_date: Option<Value>, // 现金流日期

    #[serde(rename = "COUPON_IR")]
    pub coupon_ir: Option<Value>, // 票面利率

    #[serde(rename = "PARAM_NAME")]
    pub param_name: Option<Value>, // 参数名

    #[serde(rename = "ISSUE_TYPE")]
    pub issue_type: Option<Value>, // 发行方式

    #[serde(rename = "EXECUTE_REASON_SH")]
    pub execute_reason_sh: Option<Value>, // 回售触发原因（深市）

    #[serde(rename = "PAYDAYNEW")]
    pub paydaynew: Option<Value>, // 付息日

    #[serde(rename = "CURRENT_BOND_PRICENEW")]
    pub current_bond_pricenew: Option<Value>, // 当前债券价格

    #[serde(rename = "IS_CONVERT_STOCK")]
    pub is_convert_stock: Option<Value>, // 是否可转股

    #[serde(rename = "IS_REDEEM")]
    pub is_redeem: Option<Value>, // 是否可赎回

    #[serde(rename = "IS_SELLBACK")]
    pub is_sellback: Option<Value>, // 是否可回售

    #[serde(rename = "FIRST_PROFIT")]
    pub first_profit: Option<Value>, // 首次利润
}

/// 可转债
///
/// Referer: https://data.eastmoney.com/xg/xg/?mkt=kzz
///
/// data: https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112308988225335069246_1713759765157&sortColumns=SECURITY_CODE&sortTypes=1&pageSize=50&pageNumber=1&reportName=RPT_BOND_CB_LIST&columns=ALL&quoteColumns=f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE%2Cf235~10~SECURITY_CODE~TRANSFER_PRICE%2Cf236~10~SECURITY_CODE~TRANSFER_VALUE%2Cf2~10~SECURITY_CODE~CURRENT_BOND_PRICE%2Cf237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO%2Cf239~10~SECURITY_CODE~RESALE_TRIG_PRICE%2Cf240~10~SECURITY_CODE~REDEEM_TRIG_PRICE%2Cf23~01~CONVERT_STOCK_CODE~PBV_RATIO&quoteType=0&source=WEB&client=WEB
///
/// pn: u16, page number, start from 1
///
/// pz: u16, page size, default 50
///
pub async fn rpt_bond_cb_list(pn: u16, pz: u16) -> Result<RptBondCbList> {
    // Query String Parameters:

    let host = "datacenter-web.eastmoney.com";
    //
    // callback: jQuery112308988225335069246_1713759765157
    let sort_columns = "SECURITY_CODE";
    let sort_types = 1;
    let pz = pz; // pageSize: 50
    let pn = pn; // pageNumber: 1
    let report_name = "RPT_BOND_CB_LIST";
    let columns = "ALL";
    let quote_columns =
        "f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f235~10~SECURITY_CODE~TRANSFER_PRICE,f236~10~SECURITY_CODE~TRANSFER_VALUE,f2~10~SECURITY_CODE~CURRENT_BOND_PRICE,f237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO,f239~10~SECURITY_CODE~RESALE_TRIG_PRICE,f240~10~SECURITY_CODE~REDEEM_TRIG_PRICE,f23~01~CONVERT_STOCK_CODE~PBV_RATIO";
    let quote_type = 0;
    let source = "WEB";
    let client_ = "WEB";

    let request_url = format!(
        "https://{host}/api/data/v1/get?sortColumns={sort_columns}&sortTypes={sort_types}&pageSize={pz}&pageNumber={pn}&reportName={report_name}&columns={columns}&quoteColumns={quote_columns}&quoteType={quote_type}&source={source}&client={client_}"
    );

    info!("\n (rpt_bond_cb_list) request_url= {}\n", request_url);
    // GET /api/data/v1/get?callback=jQuery112306487873133472177_1713763959921&sortColumns=SECURITY_CODE&sortTypes=1&pageSize=50&pageNumber=1&reportName=RPT_BOND_CB_LIST&columns=ALL&quoteColumns=f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE%2Cf235~10~SECURITY_CODE~TRANSFER_PRICE%2Cf236~10~SECURITY_CODE~TRANSFER_VALUE%2Cf2~10~SECURITY_CODE~CURRENT_BOND_PRICE%2Cf237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO%2Cf239~10~SECURITY_CODE~RESALE_TRIG_PRICE%2Cf240~10~SECURITY_CODE~REDEEM_TRIG_PRICE%2Cf23~01~CONVERT_STOCK_CODE~PBV_RATIO&quoteType=0&source=WEB&client=WEB HTTP/1.1
    // Accept: */*
    // Accept-Encoding: gzip, deflate, br, zstd
    // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    // Connection: keep-alive
    // Cookie: st_si=69049781651536; qgqp_b_id=b6c855887c61f555cd3dab211e3d57c7; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; fund_trade_trackid=GRBsmfBkfwzA+Mj1ArlEB6/Gi3Ptpgr/8mfRxuYiEQABMFYNXHrdjev/yp0nroi9a59YjXx0vlq210XYcT9RTg==; LToken=dc2e590b716a4dc69fe6df5d3ee6f3fc; emshistory=%5B%22%E5%8F%AF%E8%BD%AC%E5%80%BA%22%5D; HAList=ty-1-110048-%u798F%u80FD%u8F6C%u503A; st_asi=delete; st_pvi=29141230822165; st_sp=2020-08-09%2020%3A00%3A03; st_inirUrl=https%3A%2F%2Fwww.google.com%2F; st_sn=841; st_psi=20240422133240981-113300300986-1621644974; JSESSIONID=42B6BED16541612B50EF643B30DCC707
    // Host: datacenter-web.eastmoney.com
    // Referer: https://data.eastmoney.com/xg/xg/?mkt=kzz
    // Sec-Fetch-Dest: script
    // Sec-Fetch-Mode: no-cors
    // Sec-Fetch-Site: same-site
    // User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36
    // sec-ch-ua: "Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
    // sec-ch-ua-mobile: ?0
    // sec-ch-ua-platform: "macOS"

    let response = REQWEST_CLIENT.get(request_url)
        .header(reqwest::header::ACCEPT, "*/*")
        .header(reqwest::header::ACCEPT_ENCODING, "gzip, deflate, br, zstd")
        .header(reqwest::header::ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9,en;q=0.8")
        .header(reqwest::header::CACHE_CONTROL, "no-cache")
        .header(reqwest::header::CONNECTION, "keep-alive")
        // .header(reqwest::header::COOKIE, "qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-16%2016%3A57%3A06@%23%24%u4E2D%u822A%u65B0%u8D77%u822A%u7075%u6D3B%u914D%u7F6E%u6DF7%u5408A@%23%24005537; EMFUND1=01-16%2017%3A04%3A53@%23%24%u91D1%u4FE1%u6D88%u8D39%u5347%u7EA7%u80A1%u7968A@%23%24006692; EMFUND2=01-16%2020%3A01%3A56@%23%24%u5357%u65B9%u4E0A%u8BC1380ETF@%23%24510290; EMFUND3=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND4=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND5=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND6=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND7=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND8=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND9=02-02 10:30:22@#$%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; st_asi=delete; HAList=ty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-002400-%u7701%u5E7F%u96C6%u56E2%2Cty-1-601127-%u8D5B%u529B%u65AF; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=438; st_psi=20240226102321941-113200301321-9024721593")
        .header(reqwest::header::HOST, format!("{host}"))
        .header(reqwest::header::REFERER, "https://data.eastmoney.com/xg/xg/?mkt=kzz")
        .header(
            reqwest::header::USER_AGENT,
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
        )
        .header(
            "Sec-Ch-Ua",
            "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\""
        )
        .header("Sec-Ch-Ua-Mobile", "?0")
        .header("Sec-Ch-Ua-Platform", "\"macOS\"")
        .header("Sec-Fetch-Dest", "empty")
        .header("Sec-Fetch-Mode", "cors")
        .header("Sec-Fetch-Site", "same-origin")
        .send().await?;

    let body = response.text().await?;

    // println!("*** body={}\n\nhangqin\n\n", body);

    let fund: RptBondCbList = serde_json::from_str(&body)?;

    // println!("{:?}", fund);

    Ok(fund)
}

#[cfg(test)]
mod test {
    use crate::kzz::kzz_rpt_bond_cb_list::{ self, RptBondCbListResult };

    use super::RptBondCbList;

    #[tokio::test]
    async fn test_rpt_bond_cb_list() {
        let rpt: RptBondCbList = kzz_rpt_bond_cb_list::rpt_bond_cb_list(1, 3).await.unwrap();

        if let RptBondCbList { result: Some(RptBondCbListResult { data, .. }), .. } = rpt {
            for (idx, kzz) in data.iter().enumerate() {
                println!(
                    "[{idx}]{:?}, {:?}, {:?}, {:?}",
                    kzz.security_code.as_ref().unwrap().as_str().unwrap(),
                    kzz.secu_code.as_ref().unwrap().as_str().unwrap(),
                    kzz.security_name_abbr.as_ref().unwrap().as_str().unwrap(),
                    kzz.convert_stock_code.as_ref().unwrap().as_str().unwrap()
                );
            }
        }
    }
}
